From 4639f9b5527a0c7df2abb0592e90459138c07688 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 21 Jul 2016 02:47:14 +0300 Subject: [PATCH] Use LazyCell to implement lazy Config --- src/cargo/core/package.rs | 2 +- src/cargo/util/config.rs | 50 +++++++++++++------------------------ src/cargo/util/lazy_cell.rs | 16 ++++++++++-- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index c08fa0723..112d68b06 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -131,7 +131,7 @@ impl<'cfg> PackageSet<'cfg> { sources: SourceMap<'cfg>) -> PackageSet<'cfg> { PackageSet { packages: package_ids.iter().map(|id| { - (id.clone(), LazyCell::new(None)) + (id.clone(), LazyCell::new()) }).collect(), sources: RefCell::new(sources), } diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index 2c7d1befb..16298a43a 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -1,4 +1,4 @@ -use std::cell::{RefCell, RefMut, Ref, Cell}; +use std::cell::{RefCell, RefMut, Cell}; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_map::{HashMap}; use std::env; @@ -15,7 +15,7 @@ use toml; use core::shell::{Verbosity, ColorConfig}; use core::{MultiShell, Workspace}; use util::{CargoResult, CargoError, ChainError, Rustc, internal, human}; -use util::Filesystem; +use util::{Filesystem, LazyCell}; use util::toml as cargo_toml; @@ -24,11 +24,10 @@ use self::ConfigValue as CV; pub struct Config { home_path: Filesystem, shell: RefCell, - rustc: RefCell>, - values: RefCell>, - values_loaded: Cell, + rustc: LazyCell, + values: LazyCell>, cwd: PathBuf, - rustdoc: RefCell>, + rustdoc: LazyCell, target_dir: RefCell>, extra_verbose: Cell, frozen: Cell, @@ -42,11 +41,10 @@ impl Config { let mut cfg = Config { home_path: Filesystem::new(homedir), shell: RefCell::new(shell), - rustc: RefCell::new(None), + rustc: LazyCell::new(), cwd: cwd, - values: RefCell::new(HashMap::new()), - values_loaded: Cell::new(false), - rustdoc: RefCell::new(None), + values: LazyCell::new(), + rustdoc: LazyCell::new(), target_dir: RefCell::new(None), extra_verbose: Cell::new(false), frozen: Cell::new(false), @@ -96,27 +94,16 @@ impl Config { self.shell.borrow_mut() } - pub fn rustdoc(&self) -> CargoResult> { - if self.rustdoc.borrow().is_none() { - *self.rustdoc.borrow_mut() = Some(try!(self.get_tool("rustdoc"))); - } - Ok(Ref::map(self.rustdoc.borrow(), |opt| opt.as_ref().map(AsRef::as_ref).unwrap())) + pub fn rustdoc(&self) -> CargoResult<&Path> { + self.rustdoc.get_or_try_init(|| self.get_tool("rustdoc")).map(AsRef::as_ref) } - pub fn rustc(&self) -> CargoResult> { - if self.rustc.borrow().is_none() { - let path = try!(self.get_tool("rustc")); - *self.rustc.borrow_mut() = Some(try!(Rustc::new(path))); - } - Ok(Ref::map(self.rustc.borrow(), |opt| opt.as_ref().unwrap())) + pub fn rustc(&self) -> CargoResult<&Rustc> { + self.rustc.get_or_try_init(|| Rustc::new(try!(self.get_tool("rustc")))) } - pub fn values(&self) -> CargoResult>> { - if !self.values_loaded.get() { - try!(self.load_values()); - self.values_loaded.set(true); - } - Ok(self.values.borrow()) + pub fn values(&self) -> CargoResult<&HashMap> { + self.values.get_or_try_init(|| self.load_values()) } pub fn cwd(&self) -> &Path { &self.cwd } @@ -354,7 +341,7 @@ impl Config { !self.frozen.get() && !self.locked.get() } - fn load_values(&self) -> CargoResult<()> { + fn load_values(&self) -> CargoResult> { let mut cfg = CV::Table(HashMap::new(), PathBuf::from(".")); try!(walk_tree(&self.cwd, |mut file, path| { @@ -376,11 +363,10 @@ impl Config { }).chain_error(|| human("Couldn't load Cargo configuration"))); - *self.values.borrow_mut() = match cfg { - CV::Table(map, _) => map, + match cfg { + CV::Table(map, _) => Ok(map), _ => unreachable!(), - }; - Ok(()) + } } fn scrape_target_dir_config(&mut self) -> CargoResult<()> { diff --git a/src/cargo/util/lazy_cell.rs b/src/cargo/util/lazy_cell.rs index a13eaf31b..3cdaa6416 100644 --- a/src/cargo/util/lazy_cell.rs +++ b/src/cargo/util/lazy_cell.rs @@ -16,8 +16,8 @@ pub struct LazyCell { impl LazyCell { /// Creates a new empty lazy cell. - pub fn new(init: Option) -> LazyCell { - LazyCell { inner: UnsafeCell::new(init) } + pub fn new() -> LazyCell { + LazyCell { inner: UnsafeCell::new(None) } } /// Put a value into this cell. @@ -52,4 +52,16 @@ impl LazyCell { self.inner.into_inner() } } + + /// Borrows the contents of this lazy cell, initializing it if necessary. + pub fn get_or_try_init(&self, init: F) -> Result<&T, Error> + where F: FnOnce() -> Result + { + if self.borrow().is_none() { + if let Err(_) = self.fill(try!(init())) { + unreachable!(); + } + } + Ok(self.borrow().unwrap()) + } } -- 2.30.2